
package CSS::Preprocessor::ExpressionBlock;

use strict;
use warnings;
use fields qw(
    expressions
    scope
);
use overload '""' => sub{$_[0]->as_string};

use Carp;

sub parse {
    my ($class, $parser, $context) = @_;

    my $toker = $parser->tokenizer;

    $toker->require_punctuation('{');

    my @exprs = ();
    my $scope = $parser->push_active_scope;

    while (1) {
        my $next = $toker->peek_token();

        if (UNIVERSAL::isa($next, 'CSS::Preprocessor::Token::Punctuation')) {
            if ($next->chars eq '}') {
                last;
            }
            elsif ($next->chars eq ';') {
                $toker->require_punctuation(';');
                next;
            }
        }

        push @exprs, CSS::Preprocessor::Expression->parse($parser, $context);

        # Semicolons are required except in ruleset context
        # FIXME: Refactor this so that it isn't near-duplicated
        if ($context != CSS::Preprocessor::Expression::RULESET_CONTEXT) {
            my $next = $toker->peek_token();
            if ($next->chars eq '}') {
                last;
            }
            else {
                $toker->require_punctuation(';');
            }
        }
    }

    $parser->pop_active_scope($scope);

    $toker->require_punctuation('}');

    return $class->new($scope, @exprs);
}

sub new {
    my ($class, $scope, @expressions) = @_;

    my $self = fields::new($class);

    $self->{expressions} = \@expressions;
    $self->{scope} = $scope;

    return $self;
}

sub expressions {
    return $_[0]->{expressions};
}

sub scope {
    return $_[0]->{scope};
}

sub as_string {
    my $self = shift;
    return "{".join('; ', @{$self->{expressions}})."}";
}

=head1 NAME

CSS::Preprocessor::ExpressionBlock - Class representing a block of expressions that has a scope

=cut

1;

